package org.example;

import lombok.AllArgsConstructor;
import lombok.Data;
import redis.clients.jedis.*;
import java.util.Set;

/**
 * Redis连接配置管理类
 * 支持单机、哨兵和集群三种模式
 *
 * @author fxab
 * @date 2025/04/06
 */
@Data
@AllArgsConstructor
public class ConnectionConfig {
    public enum Mode { SINGLE, SENTINEL, CLUSTER }

    private final Mode mode;          // 当前连接模式
    private JedisPool jedisPool;      // 单机/哨兵连接池
    private JedisSentinelPool sentinelPool; // 哨兵专用连接池
    private JedisCluster jedisCluster; // 集群客户端


    /**
     * 单机模式构造器
     *
     * @param host Redis服务器地址
     * @param port Redis服务器端口
     */
    public ConnectionConfig(String host, int port) {
        this.mode = Mode.SINGLE;
        this.jedisPool = new JedisPool(buildPoolConfig(), host, port);
        validateConnection();
    }

    /**
     * 哨兵模式构造器
     *
     * @param masterName 主节点名称
     * @param sentinels  哨兵地址集合
     */
    public ConnectionConfig(String masterName, Set<String> sentinels) {
        this.mode = Mode.SENTINEL;
        this.sentinelPool = new JedisSentinelPool(masterName, sentinels, buildPoolConfig());
        validateConnection();
    }

    /**
     * 集群模式构造器
     *
     * @param clusterNodes 集群节点集合
     */
    public ConnectionConfig(Set<HostAndPort> clusterNodes) {
        this.mode = Mode.CLUSTER;
        this.jedisCluster = new JedisCluster(clusterNodes,
                5000, // 连接超时5秒
                5000, // 读写超时5秒
                3,    // 最大重试次数
                buildPoolConfig());
        validateConnection();
    }


    /**
     * 获取Jedis实例（仅单机和哨兵模式）
     *
     * @return {@link Jedis }
     */
    public Jedis getResource() {
        switch (mode) {
            case SINGLE: return jedisPool.getResource();
            case SENTINEL: return sentinelPool.getResource();
            default: throw new UnsupportedOperationException("集群模式请使用getCluster()");
        }
    }

    /**
     * 获取集群客户端（仅集群模式）
     *
     * @return {@link JedisCluster }
     */
    public JedisCluster getCluster() {
        if (mode != Mode.CLUSTER) throw new IllegalStateException("当前不是集群模式");
        return jedisCluster;
    }

    /**
     * 关闭所有连接资源
     */
    public void close() {
        switch (mode) {
            case SINGLE:
                if (jedisPool != null && !jedisPool.isClosed()) {
                    jedisPool.close();
                }
                break;
            case SENTINEL:
                if (sentinelPool != null && !sentinelPool.isClosed()) {
                    sentinelPool.close();
                }
                break;
            case CLUSTER:
                if (jedisCluster != null) {
                    try {
                        jedisCluster.close();
                    } catch (Exception e) {
                        System.err.println("关闭集群连接异常: " + e.getMessage());
                    }
                }
                break;
        }
    }


    /**
     * 创建通用连接池配置
     *
     * @return {@link JedisPoolConfig }
     */
    private static JedisPoolConfig buildPoolConfig() {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(8);        // 最大连接数
        config.setMaxIdle(8);         // 最大空闲连接
        config.setMinIdle(1);         // 最小空闲连接
        config.setTestOnBorrow(true); // 借出连接时验证
        config.setTestOnReturn(true); // 归还连接时验证
        return config;
    }

    /**
     * 验证连接有效性
     */
    private void validateConnection() {
        try {
            if (mode == Mode.CLUSTER) {
                // 集群模式检查第一个节点是否可达
                jedisCluster.getClusterNodes().values().iterator().next().getResource().ping();
            } else {
                // 单机/哨兵模式获取并立即释放连接
                Jedis jedis = getResource();
                jedis.close();
            }
        } catch (Exception e) {
            throw new IllegalStateException("Redis连接验证失败: " + e.getMessage());
        }
    }

    /**
     * 获取模式
     *
     * @return {@link Mode }
     */
    public Mode getMode() {
        return mode;
    }



}
